﻿using System;
using System.Collections.Generic;
using System.Linq;
using PS.WSSDeploy.Client;
using PS_WSSDeploy_Package.Settings;

namespace PS_WSSDeploy_Package.Client
{
    public class ClientContainer : IClient, IClientSettings
    {
        private Config ClientConfig { get; set; }

        private WSSDeployClient Client
        {
            get
            {
                var prms = new WSSDeployClient.Params
                {
                    ServerName = ClientConfig.ServerName,
                    ServicePort = ClientConfig.ServicePort,
                    CertificateFileName = ClientConfig.UseCertificate ? ClientConfig.CertificateFileName : string.Empty,
                    CertificateFilePassword = ClientConfig.CertificateFilePassword,
                    IdentityDnsName = ClientConfig.IdentityDnsName
                };
                return new WSSDeployClient(prms);
            }
        }

        private WSSDeployClient GetClient(string serverName)
        {
            var prms = new WSSDeployClient.Params
            {
                ServerName = serverName,
                ServicePort = ClientConfig.ServicePort,
                CertificateFileName = ClientConfig.UseCertificate ? ClientConfig.CertificateFileName : string.Empty,
                CertificateFilePassword = ClientConfig.CertificateFilePassword,
                IdentityDnsName = ClientConfig.IdentityDnsName
            };
            return new WSSDeployClient(prms);
        }

        public ClientContainer(string solutionPath)
        {
            ClientConfig = Config.Create(solutionPath);
        }

        private void ClientOp(Action<WSSDeployClient> action)
        {
            var activeServerName = ClientConfig.ActiveServerName;
            var servers = new List<string>(activeServerName.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries));
            foreach (var client in servers.Select(GetClient))
            {
                action(client);
            }
        }

        private void ClientSimpleServerOp(Action<WSSDeployClient> action)
        {
            var activeServerName = ClientConfig.ActiveServerName;
            var servers = new List<string>(activeServerName.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries));
            if(servers.Count > 0)
            {
                var client = GetClient(servers[0]);
                action(client);
            }
        }
        
        private static void ThrowEmptyWebAppList(string webAppList)
        {
            if (string.IsNullOrEmpty(webAppList))
                throw new ApplicationException("You did not select a web application");
        }

        public void Create(string fileName)
        {
            ClientSimpleServerOp(c => c.Create(fileName));
        }

        public void Deploy(string fileName)
        {
            var webAppsList = GetWebAppListAsString();
            ThrowEmptyWebAppList(webAppsList);
            ClientSimpleServerOp(c => c.Deploy(fileName, ClientConfig.WspContainsResources, webAppsList));
        }

        public void Uninstall(string fileName)
        {
            var webAppsList = GetWebAppListAsString();
            ThrowEmptyWebAppList(webAppsList);
            ClientSimpleServerOp(c => c.Uninstall(fileName, ClientConfig.WspContainsResources, webAppsList));
        }

        public void CopyToRoot(string sharePointRootFolder, string path)
        {
            ClientOp(c => c.CopyToRoot(sharePointRootFolder, path));
        }

        public void CopyToRoot(List<RootFile> rootFiles)
        {
            ClientOp(c => c.CopyToRoot(rootFiles));
        }

        public int CopyToGAC(string path)
        {
            int ret = 0;
            ClientOp(c => ret = c.CopyToGAC(path));
            return ret;
        }

        public int CopyTargetToGAC(string targetPath)
        {
            int ret = 0;
            ClientOp(c => ret = c.CopyTargetToGAC(targetPath));
            return ret;
        }

        public void RecycleAppPools()
        {
            var webAppsList = GetWebAppListAsString();
            ThrowEmptyWebAppList(webAppsList);
            ClientOp(c => c.RecycleAppPools(webAppsList));
        }

        public void StartRemoteDebuggerMonitor()
        {
            ClientOp(c => c.StartRemoteDebuggerMonitor(ClientConfig.RemoteDebuggerLogin, ClientConfig.RemoteDebuggerPassword));
        }

        public void KillRemoteDebuggerMonitor()
        {
            ClientOp(c => c.KillRemoteDebuggerMonitor());
        }

        public void CreateDebugAccount()
        {
            ClientOp(c => c.CreateDebugAccount(ClientConfig.RemoteDebuggerLogin, ClientConfig.RemoteDebuggerPassword));
        }

        public List<string> GetFarmServerList(string serverName)
        {
            var client = GetClient(serverName);
            var serverList = client.GetFarmServerList();
            var ret = new List<string>(serverList.Split(new[] {"#;"}, StringSplitOptions.RemoveEmptyEntries));
            return ret;
        }

        public List<string> GetWebApplicationList(string serverName)
        {
            var client = GetClient(serverName);
            var webAppList = client.GetWebApplicationList();
            var list = new List<string>(webAppList.Split(new[] { "#;" }, StringSplitOptions.RemoveEmptyEntries));
            var ret = new List<string>();
            int idx = 0;
            foreach (var item in list)
            {
                if(idx % 2 == 0) ret.Add(item);
                ++idx;
            }
            return ret;
        }

        public Config Config
        {
            get { return ClientConfig; }
        }

        private string GetWebAppListAsString()
        {
            var webApps = ClientConfig.WebAppsList;
            return string.Join("#;", webApps.Where(w => w.Selected).Select(w => w.Name).ToArray());
        }
    }
}
